<?php

declare (strict_types=1);
/**
 * @copyright 深圳市易果网络科技有限公司
 * @version 1.0.0
 * @link https://dayiguo.com
 */

namespace App\Service\User;

use App\Constants\Constants;
use App\Dao\OrderDao;
use App\Dao\UserAliDao;
use App\Dao\UserBusinessFavDao;
use App\Dao\UserCouponDao;
use App\Dao\UserDao;
use App\Dao\UserFavDao;
use App\Dao\UserWechatDao;
use App\Kernel\Util\UserJwtInstance;
use App\Service\Service;

use Hyperf\Di\Annotation\Inject;

/**
 * 用户服务
 *
 * @author 刘兴永(aile8880@qq.com)
 * @package App\Service\Admin
 */
class UserService extends Service
{
    /**
     * @Inject
     * @var UserDao
     */
    public $dao;

    /**
     * @Inject
     * @var UserBusinessFavDao
     */
    public $user_business_fav_dao;

    /**
     * @Inject
     * @var UserFavDao
     */
    public $user_fav_dao;

    /**
     * @Inject
     * @var UserCouponDao
     */
    public $user_coupon_dao;

    /**
     * @Inject
     * @var OrderDao
     */
    public $order_dao;

    /**
     * @Inject
     * @var UserWechatDao
     */
    public $user_wechat_dao;

    /**
     * @Inject
     * @var UserAliDao
     */
    public $user_ali_dao;

    /**
     * 线下扫码
     * @param string $phone
     * @param string $code
     * @param int $id
     * @param int $type
     * @param string|null $invitation_code
     * @return array
     */
    public function scanLogin(string $phone, string $code, int $id, int $type, string $invitation_code = null)
    {
        // 判断验证码是否输入正确
        $record = $this->redis->get(Constants::CODE_REDIS_PREFIX . $phone);
        $record = !$record ?: json_decode($record, true);
        if (!$record || !isset($record['code']) || (string)$record['code'] !== $code) {
            $this->error('COMMON.CODE_ERROR');
        }
        $this->redis->del(Constants::CODE_REDIS_PREFIX . $phone);

        // 邀请码
        $parent = null;
        if ( !empty($invitation_code) ) {
            $parent = $this->dao->getParentByIdentityCode($invitation_code);
        }

        $password = password_hash($phone, PASSWORD_DEFAULT );

        $userByPhone = $this->dao->loginByPhone($phone);
        $user_old = 1;
        if( $userByPhone ) {
            $user_old = 2;
        }

        // 获取或创建用户
        if (!$user = $this->dao->loginByPhoneOrCreate($phone, $password ,$parent ? $parent->id : 0)) {
            $this->error('USER.LOGIN_FAILED');
        }
        //判断 微信还是支付宝
        if( $type == 1 ) {
            $this->user_wechat_dao->update(['id'=>$id],['user_id'=>$user->id]);
        } else if( $type == 2) {
            $this->user_ali_dao->update(['id'=>$id],['user_id'=>$user->id]);
        }

        // 首次登陆，生成用户唯一识别码，可以作为邀请码。以数据库自增主键作为前缀，可以保证生成值的唯一性
        if (!$user->identity_code) {
            $user->identity_code = strtoupper(substr(md5(uniqid('identity_code_' . $user->id)), 0, 6));
            $user->save();
        }

        // check user status
        if ($user->status !== true) {
            $this->error('USER.STATUS_EXCEPTION');
        }

        // check user group
        if (!$user->group || $user->group->status !== true) {
            $this->error('USER.GROUP_STATUS_EXCEPTION');
        }

        return [
            'old' => $user_old,
            'token' => (string)UserJwtInstance::instance()->encode($user),
        ];
    }

    /**
     * 分享登录
     * @param string $phone
     * @param string $code
     * @param string|null $invitation_code
     * @return array
     */
    public function shareLogin(string $phone, string $code,string $invitation_code = null)
    {
        // 判断验证码是否输入正确
        $record = $this->redis->get(Constants::CODE_REDIS_PREFIX . $phone);
        $record = !$record ?: json_decode($record, true);
        if (!$record || !isset($record['code']) || (string)$record['code'] !== $code) {
            $this->error('COMMON.CODE_ERROR');
        }
        $this->redis->del(Constants::CODE_REDIS_PREFIX . $phone);
        // 邀请码
        $parent = null;
        if ( !empty($invitation_code) ) {
            $parent = $this->dao->getParentByIdentityCode($invitation_code);
        }

        $password = password_hash($phone, PASSWORD_DEFAULT );

        $old = $this->dao->getPhoneShare($phone,['id']);
        $user_old = 0;
        if( $old ) {
            $user_old = 1;
        }

        // 获取或创建用户
        if (!$user = $this->dao->loginByPhoneOrCreate($phone, $password ,$parent ? $parent->id : 0)) {
            $this->error('USER.LOGIN_FAILED');
        }

        // 首次登陆，生成用户唯一识别码，可以作为邀请码。以数据库自增主键作为前缀，可以保证生成值的唯一性
        if (!$user->identity_code) {
            $user->identity_code = strtoupper(substr(md5(uniqid('identity_code_' . $user->id)), 0, 6));
            $user->save();
        }

        // check user status
        if ($user->status !== true) {
            $this->error('USER.STATUS_EXCEPTION');
        }

        // check user group
        if (!$user->group || $user->group->status !== true) {
            $this->error('USER.GROUP_STATUS_EXCEPTION');
        }

        return [
            'token' => (string)UserJwtInstance::instance()->encode($user),
            'old' => $user_old
        ];
    }

    /**
     * 用户登录处理
     *
     * @param string $phone 手机号码
     * @param string $login_pwd  登录密码
     * @return array
     */
    public function login(string $phone, string $login_pwd)
    {

        // 获取或创建用户
        if (!$user = $this->dao->loginByPhone($phone)) {
            $this->error('USER.LOGIN_FAILED');
        }
        //验证密码
        if( !password_verify( $login_pwd, $user->login_pwd ) ) {
            $this->error('USER.REGISTER_FAIL');
        }

        // 首次登陆，生成用户唯一识别码，可以作为邀请码。以数据库自增主键作为前缀，可以保证生成值的唯一性
        if (!$user->identity_code) {
            $user->identity_code = strtoupper(substr(md5(uniqid('identity_code_' . $user->id)), 0, 6));
            $user->save();
        }

        // check user status
        if ($user->status !== true) {
            $this->error('USER.STATUS_EXCEPTION');
        }

        // check user group
        if (!$user->group || $user->group->status !== true) {
            $this->error('USER.GROUP_STATUS_EXCEPTION');
        }

        return [
            'token' => (string)UserJwtInstance::instance()->encode($user),
            'is_addr' => empty($user->district_id) ? 0 : $user->district_id
        ];
    }

    /**
     * 用户注册处理
     *
     * @param string $phone 手机号码
     * @param string $code 验证码
     * @param string|null $invitation_code 上级ID
     * @param string $login_pwd 密码
     * @return array
     */
    public function register(string $phone, string $code, $login_pwd,  string $invitation_code = null)
    {
        // 获取或创建用户
        if ( $this->dao->loginByPhone($phone) ) {
            $this->error('USER.NOT_PHONE');
        }

        // 判断验证码是否输入正确
        $record = $this->redis->get(Constants::CODE_REDIS_PREFIX . $phone);
        $record = !$record ?: json_decode($record, true);
        if (!$record || !isset($record['code']) || (string)$record['code'] !== $code) {
            $this->error('COMMON.CODE_ERROR');
        }
        $this->redis->del(Constants::CODE_REDIS_PREFIX . $phone);

        // 邀请码
        $parent = null;
        if ( !empty($invitation_code) ) {
            $parent = $this->dao->getParentByIdentityCode($invitation_code);
        }
        $password = password_hash($login_pwd, PASSWORD_DEFAULT );
        // 获取或创建用户
        if (!$user = $this->dao->loginByCreate($phone, $password ,$parent ? $parent->id : 0)) {
            $this->error('USER.LOGIN_FAILED');
        }

        // 首次登陆，生成用户唯一识别码，可以作为邀请码。以数据库自增主键作为前缀，可以保证生成值的唯一性
        if (!$user->identity_code) {
            $user->identity_code = strtoupper(substr(md5(uniqid('identity_code_' . $user->id)), 0, 6));
            $user->save();
        }

        // check user status
        if ($user->status !== true) {
            $this->error('USER.STATUS_EXCEPTION');
        }

        // check user group
        if (!$user->group || $user->group->status !== true) {
            $this->error('USER.GROUP_STATUS_EXCEPTION');
        }

        return [
            'token' => (string)UserJwtInstance::instance()->encode($user)
        ];
    }

    /**
     * 获取用户资料
     *
     * @return mixed
     */
    public function getUserInfo()
    {
        $user = UserJwtInstance::instance()->build()->getUser();

        $user['user_business_fav_count'] = $this->user_business_fav_dao->count(['user_id' => uid()]);
        $user['user_integral'] = $this->redis->hGet('txh:user:'.uid(),'integral') ?$this->redis->hGet('txh:user:'.uid(),'integral'):'0.00';
        $user['user_fav_count'] = $this->user_fav_dao->count(['user_id' => uid()]);
        $user['user_integral_count'] = 0;
        $user['user_coupon_count'] = $this->user_coupon_dao->getUserBusinessCouponByUserId([
            'user_id' => uid(),
            'type' => $this->user_coupon_dao::TYPE_COUPON,
            'status' => $this->user_coupon_dao::STATUS_PAID,
            'expire_time' => ['>', time()],
            'use_time' => 0
        ]);
        $user['user_cash_coupons_count'] = $this->user_coupon_dao->getUserBusinessCouponByUserId([
            'user_id' => uid(),
            'type' => $this->user_coupon_dao::TYPE_CASH_COUPON,
            'status' => $this->user_coupon_dao::STATUS_PAID,
            'expire_time' => ['>', time()],
            'use_time' => 0
        ]);
        $user['user_business_coupons_count'] = 0;
        $user['user_order_unpaid'] = $this->order_dao->count([
            'status' => $this->order_dao::STATUS_UNPAID,
            'user_id' => uid()
        ]);
        $user['user_order_paid'] = $this->order_dao->count([
            'status' => $this->order_dao::STATUS_PAID,
            'user_id' => uid()
        ]);
        $user['user_order_delivery'] = $this->order_dao->count([
            'status' => $this->order_dao::STATUS_DELIVERY,
            'user_id' => uid()
        ]);
        $user['user_order_received'] = $this->order_dao->count([
            'status' => $this->order_dao::STATUS_RECEIVED,
            'user_id' => uid()
        ]);

        $user['user_addr'] = $user['province'].$user['city'].$user['district'];

        if( $user['group']['name'] == "会员" ) {
            $user['user_is_channel'] = 1;
        } else if( $user['group']['name'] == "渠道商" ){
            $user['user_is_channel'] = 2;
        }

        // 隐藏重要的字段
        $user->makeHidden(['id', 'parent_id', 'group_id','login_pwd', 'safe_pwd', 'status', 'created_at', 'updated_at', 'deleted_at']);

        // 用户组
        $user->group->makeHidden(['id', 'status']);

        return $user;
    }

    /**
     * 找回密码 - 验证手机
     * @param string $phone
     * @param string $code
     * @return mixed
     */
    public function retrievePhone(string $phone, string $code)
    {
        // 判断验证码是否输入正确
        $record = $this->redis->get(Constants::CODE_REDIS_PREFIX . $phone);
        $record = !$record ?: json_decode($record, true);
        if (!$record || !isset($record['code']) || (string)$record['code'] !== $code) {
            $this->error('COMMON.CODE_ERROR');
        }
        $this->redis->del(Constants::CODE_REDIS_PREFIX . $phone);

        $result = $this->dao->getPhoneByUser( $phone, [
            'id'
        ]);

        return $result;
    }
}